/*glibc-doc, instalar*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#define SHELL_NAME "bumsh"
#define PROMPT "$> "

/*global variables*/

int keep_running = 1; /*control the main loop*/


/**/


//verificar argumentos para comandos built-in
//por exemplo cd diretório de destino
//
//seria legal mudar o formato do prompt 
//para mostrar parte do diretório corrente
//
int process_builtin(char **command)
{
	char *comando = command[0];
	char dir[100];
	if (!strcmp(comando, "exit"))
	{
		keep_running = 0;
		return 0;
    }
	else if(!strcmp(comando,"pwd"))
	{

		printf("%s\n",getenv("PWD"));
		return 0;		
	}
	else if(!strcmp(comando,"help"))
	{
		return 0;
	}
	else if(!strcmp(comando,"jobs"))
	{
		return 0;
	}
	else if(!strcmp(comando,"fg"))
	{
		return 0;
	}
	else if(!strcmp(comando,"bg"))
	{
		return 0;
	}
	else if(!strcmp(comando, "cd"))
	{
	  if(!chdir((char*)command[1]))
	  {  
        getcwd(dir,100*sizeof(char));		
		setenv("PWD",dir,1);
		
	  }	
	  else fprintf(stderr,"%s: %s\n",SHELL_NAME,strerror(errno));
	  
	  return 0;
	}
	return 1;
}

void close_pipe(int fds[])
{
    close(fds[0]);
    close(fds[1]);
}
  
void set_read(int lpipe[])
{
    close(lpipe[1]);
    dup2(lpipe[0], 0);
}
  
void set_write(int rpipe[])
{
    close(rpipe[0]);
    dup2(rpipe[1], 1);
}
  
void copy_pipe(int* src, int* dst)
{
    dst[0] = src[0];
    dst[1] = src[1];
}

//sem utilidade 
int processcommand(char **cmd ){
	
	return 0;
}


void tokenize(char *msg, char *array[],char *delim)
{
	int i = 0, j = 0;
	char *result = NULL;
	char *buf = (char *) malloc(sizeof(char) *strlen(msg) + 1);
	strcpy(buf, msg);

	result = strtok(buf, delim);
	while(result != NULL)
	{
		array[i] = result;
		result = strtok(NULL, delim);
		i++;
	} 
	array[i] = '\0';
}

void fork_and_pipe(char** args, int* lpipe, int* rpipe)
{
    int status;
	pid_t pid = fork();
    if(pid == 0)
    {
	        if(lpipe)
	            set_read(lpipe);
	        if(rpipe)
	            set_write(rpipe);
	        execvp(args[0], args);
	        perror(args[0]);
	        exit(EXIT_FAILURE);
	    }
    else
		{
	        if(lpipe)
	            close_pipe(lpipe);
			wait(&status);
		}
}


int main(int argc, char **argv)
{

	int lpipe[2], rpipe[2];
	char clbuffer[1000]; /* command line*/
	char *command[1000]; /*commandos a serem executados*/
	char *aux[100];
	char **aux2;
	char ***cmds;
	char *diretorioatual;
	int ncmds;
	pid_t pid;
	int status, i = 0, j = 0, havepipe = 0;
	char **command_line;
	char *user = getenv("USER");

	while(keep_running)
    {
		
		diretorioatual = getenv("PWD");
	  //  daux = strstr(diretorioatual,(char*)getenv("HOME"));
	//	if(daux != NULL)
	//		strcpy(daux,"~");
		cmds = (char***) malloc (100*sizeof(char**));
		for(i=0;i<100;i++)
			cmds[i] = (char**) malloc(100*sizeof(char*));
		for(i=0;i<100;i++)
			for(j=0;j<100;j++)
				cmds[i][j] = (char*) malloc(100*sizeof(char));
		
		printf("%s@%s%s",user,diretorioatual,PROMPT);
      
		fgets(clbuffer,1000,stdin);

		if(clbuffer[0]=='\n')
		{
			clbuffer[0]='\0';
			continue;
		}		
        
		clbuffer[strlen(clbuffer)-1] = '\0';
		
		
		/*process command line.*/
		//printf("0\n");
		havepipe = 0;
		tokenize(clbuffer,command,"|\0");
		if(command[1]!= '\0')
			havepipe = 1;
		//tokenize(redirecionamentos);
      //  strcat(caux, command[0][0]command[0][1]);
		//if(!strcmp(caux,"ls"))
		//{
		//	strcat(command[0]," --color");
		//}
		i = 0;
		j = 0;
		while(command[i] != '\0')
		{
			
			//printf("entrei no while\n");
			aux[0] = '\0';
			tokenize(command[i], aux," \0");			
			//printf("tokenizei para aux\n");
			while(aux[j] != '\0')
			{
				strcpy(cmds[i][j], aux[j]);
			
				j++;
			}
			cmds[i][j] = '\0';
			j = 0;
			i++;
		}
		//printf("2\n");
		cmds[i][0] = "\0";
		ncmds = i;
		
//		aux2 = cmds[0];
//		aux2[2] = "\0";
//		printf("\n\n%s %s\n\n", aux2[0], aux2[1]);

		//printf("atencao:\n\n%s %s\n\n",cmds[1][0],cmds[1][1]);

		if(havepipe == 1) //avemmos pipe! 
		{	
			pipe(rpipe);
			fork_and_pipe(cmds[0],NULL,rpipe);
			copy_pipe(rpipe, lpipe);

			for(i = 1; i< ncmds - 1; i++)
			{
				pipe(rpipe);
				fork_and_pipe(cmds[i],lpipe,rpipe);
				copy_pipe(rpipe, lpipe);
			}		
			fork_and_pipe(cmds[ncmds-1], lpipe, NULL);
		}
		else {
		
			if(process_builtin(cmds[0]))/*if it's a builtin command, do it*/
			{
	  
				pid = fork (); /*form now on we may have two processes*/

				if (pid < 0)
				{
					
					fprintf(stderr,"%s: %s\n",SHELL_NAME,strerror(errno));
					exit(EXIT_FAILURE);
				}

				if(pid > 0) /*this is the father*/				
				{
					wait(&status);
				}
				else        /*this is the child*/
				{
					/*colore o ls adicionando o argumento --color*/
					if(!strcmp(cmds[0][0],"ls"))
					{
						i=1;
						while(cmds[0][i] != NULL)
							i++;
						cmds[0][i] = "--color";
						cmds[0][i+1] = NULL;
					}
					command_line = cmds[0];
					execvp(command_line[0],command_line);

					printf("%s : command not found\n",command_line[0]);
					return EXIT_FAILURE;
				}
			}
			//diretorioatual = getenv("PWD");
		}	
		//	for(i=0;i<100;i++)
		//		for(j=0;j<100;j++)
		//			free(cmds[i][j]);
		//	for(i=0;i<100;i++)
		//		free(cmds[i]);
		//	free(cmds);
	}
	return EXIT_SUCCESS;
}
